"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 极致RTO-数据库系统类
Case Name   : gsc开关打开，极致RTO场景下，进行switchover、failover，新主执行ddl，dml功能正常
Create At   : 2022/5/10
Owner       : @peilinqian
Description :
    1、设置极致RTO及GSC参数;
    2、重启数据库，使参数生效;
    3、主机进行ddl，dml;
    查询主备状态
    4、备机执行switchover;
    查询主备状态
    5、新主机对相同表进行ddl，dml;
    查询主备状态
    6、原主执行failover;
    现主机stop
    原主机failover
    备机启动
    7、主机对相同表进行ddl，dml;
    查询主备状态
Expect      :
    1、设置极致RTO及GSC参数; 成功
    2、重启数据库，使参数生效; 重启成功
    3、主机进行ddl，dml; 执行成功
    查询主备状态正常
    4、备机执行switchover; 执行成功
    查询主备状态正常
    5、新主机对相同表进行ddl，dml; 执行成功
    查询主备状态正常
    6、原主执行failover; 执行成功
    现主机stop成功
    原主机failover成功
    备机启动成功
    7、主机对相同表进行ddl，dml; 执行成功
    查询主备状态正常
History     :
"""
import os
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node

pri_sh = CommonSH('PrimaryDbUser')
node_num = pri_sh.get_node_num()


@unittest.skipIf(3 != node_num, '非1+2环境不执行')
class GscTestCase(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)}:start----')
        self.log.info("----this is setup----")
        self.pri_root = Node(node='PrimaryRoot')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.sta_1_sh = CommonSH('Standby1DbUser')
        self.com = Common()
        self.constant = Constant()
        self.max_num = 10000
        self.table_test = 'tb_gsc0029'
        self.create_sql = f'''drop table if exists {self.table_test};
            create table {self.table_test}(id int);
            insert into {self.table_test} values 
            (generate_series(1,{self.max_num}));'''
        self.select_sql = f'select count(*) from {self.table_test};'
        self.drop_sql = f'drop table {self.table_test};'

    def test_main(self):
        step_txt = '----step0:查询参数初始值;----'
        self.log.info(step_txt)
        self.init_para1 = self.com.show_param('replication_type')
        self.init_para2 = self.com.show_param('recovery_parse_workers')
        self.init_para3 = self.com.show_param('recovery_redo_workers')
        self.init_para4 = self.com.show_param('hot_standby')
        self.init_para5 = self.com.show_param('enable_global_syscache')

        step_txt = '----step1:设置极致RTO及GSC参数; expect:成功----'
        self.log.info(step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        'replication_type=1')
        self.assertTrue(msg, '执行失败:' + step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        'recovery_parse_workers=4')
        self.assertTrue(msg, '执行失败:' + step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        'recovery_redo_workers=4')
        self.assertTrue(msg, '执行失败:' + step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        'hot_standby=off')
        self.assertTrue(msg, '执行失败:' + step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        f"enable_global_syscache= on")
        self.assertTrue(msg, '执行失败:' + step_txt)

        step_txt = '----step2:重启数据库，使参数生效; expect:重启成功----'
        self.log.info(step_txt)
        stop_result = self.pri_sh.stop_db_cluster()
        start_result = self.pri_sh.start_db_cluster()
        self.assertTrue(stop_result, '执行失败:' + step_txt)
        self.assertTrue(start_result, '执行失败:' + step_txt)

        step_txt = '----step3:主机进行ddl，dml; expect:执行成功----'
        self.log.info(step_txt)
        create_result = self.pri_sh.execut_db_sql(self.create_sql)
        self.log.info(create_result)
        select_result = self.pri_sh.execut_db_sql(self.select_sql)
        self.log.info(select_result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(str(self.max_num), select_result, '执行失败:' + step_txt)

        self.log.info('----查看主机query，同步是否正常----')
        self.pri_sh.check_location_consistency('primary', node_num)
        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

        step_txt = '----step4:备机执行switchover; expect:执行成功----'
        self.log.info(step_txt)
        suc_msg = self.constant.SWITCH_SUCCESS_MSG
        switchover_result = self.sta_1_sh.execute_gsctl('switchover', suc_msg)
        self.assertTrue(switchover_result, '执行失败:' + step_txt)
        refresh_result = self.sta_1_sh.exec_refresh_conf()
        self.assertTrue(refresh_result, '执行失败:' + step_txt)
        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

        step_txt = '----step5:新主机对相同表进行ddl，dml; expect:执行成功----'
        self.log.info(step_txt)
        create_result = self.sta_1_sh.execut_db_sql(self.create_sql)
        self.log.info(create_result)
        select_result = self.sta_1_sh.execut_db_sql(self.select_sql)
        self.log.info(select_result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(str(self.max_num), select_result, '执行失败:' + step_txt)

        self.log.info('----查看主机query，同步是否正常----')
        self.sta_1_sh.check_location_consistency('primary', node_num)
        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

        step_txt = '----step6:原主执行failover; expect:执行成功----'
        self.log.info(step_txt)
        self.log.info('----现主机stop----')
        stop_msg = self.sta_1_sh.stop_db_instance()
        self.assertIn(self.constant.GS_CTL_STOP_SUCCESS_MSG, stop_msg,
                      '执行失败:' + step_txt)
        self.log.info('----原主机failover----')
        suc_msg = self.constant.FAILOVER_SUCCESS_MSG
        failover_result = self.pri_sh.execute_gsctl('failover', suc_msg)
        self.assertTrue(failover_result, '执行失败:' + step_txt)
        refresh_result = self.pri_sh.exec_refresh_conf()
        self.assertTrue(refresh_result, '执行失败:' + step_txt)
        self.log.info('----备机启动----')
        start_msg = self.sta_1_sh.start_db_instance('standby')
        self.assertIn(self.constant.RESTART_SUCCESS_MSG, start_msg,
                      '执行失败:' + step_txt)

        step_txt = '----step7:主机对相同表进行ddl，dml; expect:执行成功----'
        self.log.info(step_txt)
        create_result = self.pri_sh.execut_db_sql(self.create_sql)
        self.log.info(create_result)
        select_result = self.pri_sh.execut_db_sql(self.select_sql)
        self.log.info(select_result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(str(self.max_num), select_result, '执行失败:' + step_txt)

        self.log.info('----查看主机query，同步是否正常----')
        self.pri_sh.check_location_consistency('primary', node_num)
        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

    def tearDown(self):
        step_txt = '----this is teardown----'
        self.log.info(step_txt)
        host_name = self.pri_root.sh('hostname').result()
        if self.pri_sh.check_whether_need_switch(host_name):
            self.log.info('----主备关系异常，进行恢复----')
            self.pri_sh.start_db_cluster()
            self.log.info('---进行主备切换---')
            suc_msg = self.constant.SWITCHOVER_SUCCESS_MSG
            switch_result = self.pri_sh.execute_gsctl('switchover', suc_msg)
            self.log.info(switch_result)
            refresh_result = self.pri_sh.exec_refresh_conf()
            self.log.info(refresh_result)

        step1_txt = '----清理测试表; expect:清理成功----'
        self.log.info(step1_txt)
        drop_result = self.pri_sh.execut_db_sql(self.drop_sql)
        self.log.info(drop_result)
        step2_txt = '----恢复参数为初始值并查询; expect:设置成功----'
        self.log.info(step2_txt)
        msg1 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"replication_type="
                                         f"{self.init_para1}")
        msg2 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"recovery_parse_workers="
                                         f"{self.init_para2}")
        msg3 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"recovery_redo_workers="
                                         f"{self.init_para3}")
        msg4 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"hot_standby={self.init_para4}")
        msg5 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"enable_global_syscache="
                                         f"{self.init_para5}")
        step3_txt = '----重启数据库，使参数生效; expect:重启成功----'
        self.log.info(step3_txt)
        restart_result = self.pri_sh.restart_db_cluster()
        step4_txt = '----查询数据库状态; expect:状态正常----'
        self.log.info(step4_txt)
        status_result = self.pri_sh.get_db_cluster_status('status')

        self.log.info(f'----{os.path.basename(__file__)}:end----')
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, drop_result,
                      '执行失败:' + step_txt + step1_txt)
        self.assertTrue(msg1, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(msg2, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(msg3, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(msg4, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(msg5, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(restart_result, '执行失败:' + step_txt + step3_txt)
        self.assertTrue(status_result, '执行失败:' + step_txt + step4_txt)
